﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Quellenverwaltung.Data.Source;
using Quellenverwaltung.SRU;

namespace Quellenverwaltung.UI.WPF
{
    /// <summary>
    /// Interaktionslogik für FindBarcode.xaml
    /// </summary>
    public partial class FindBarcode : UserControl
    {
        public Quellenverwaltung.Entwicklungskomponenten.BarcodeWPFHost HostForm { get; set; }
        private UI.Webcam.Webcam webcam;
        private Threads.BarcodeProcess barcodeProcess;
        private Threads.SearchSRUProcess searchProcess;
        private bool IsBarcodeRecognitionActive = false;
        private Word.Configuration configuration;

        public FindBarcode()
        {
            InitializeComponent();
            configuration = Word.Configuration.getConfiguration();

            this.BarcodeScanHelper.Visibility = Visibility.Hidden;
			this.gridSearchingIndicator.Visibility = Visibility.Hidden;
            searchProcess = new Threads.SearchSRUProcess(configuration.SRUServiceURL);
            searchProcess.ResultFound += searchProcess_ResultFound;
        }


        private void ScanBarcode_Loaded_1(object sender, RoutedEventArgs e)
        {
            barcodeProcess = new Threads.BarcodeProcess();
            barcodeProcess.ResultFound += new EventHandler<Threads.BarcodeProcessArgs>(process_ISBNFound);
            barcodeProcess.Start();

            webcam = new UI.Webcam.Webcam();
            if (webcam.isActive())
            {
                webcam.AddFrameEventHandler(videoSource_NewFrame);
                webcam.Start();

                this.IsBarcodeRecognitionActive = true;

            }
            else
            {
                this.webcamContainer.Visibility = Visibility.Collapsed;
            }

            this.editBook.HostForm = HostForm;
        }

        void videoSource_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
        {
            if (this.BarcodeScanHelper.Visibility == Visibility.Hidden)
            {
                this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
                {
                    this.BarcodeScanHelper.Visibility = Visibility.Visible;
                }, null); 
            }

            System.Drawing.Image imgforms = (Bitmap)eventArgs.Frame.Clone();

            BitmapImage bi = new BitmapImage();
            bi.BeginInit();

            MemoryStream ms = new MemoryStream();
            imgforms.Save(ms, ImageFormat.Bmp);
            ms.Seek(0, SeekOrigin.Begin);

            bi.StreamSource = ms;
            bi.EndInit();

            //Using the freeze function to avoid cross thread operations  
            bi.Freeze();

            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
            {
                picturewebcam.Source = bi;
            }, null); 

            barcodeProcess.HandleNewBitmap((Bitmap)eventArgs.Frame);
        }

        void process_ISBNFound(object sender, Quellenverwaltung.Threads.BarcodeProcessArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
            {
                System.Media.SystemSounds.Beep.Play();

                stopBarcodeRecognition();
                textBoxSearch.Text = e.Result;
                startSearch();

                // Reduziere Webcambild im Platz zu sparen
                shrinkWebcamImage();
            }, null);
        }

        private void buttonSearch_Click(object sender, RoutedEventArgs e)
        {
            startSearch();
        }

        private void startSearch()
        {
            if (String.IsNullOrEmpty(textBoxSearch.Text))
            {
                labelSearchingIndicator.Text = "Suchbegriff darf nicht leer sein";
            }
            else
            {
                if (IsBarcodeRecognitionActive)
                {
                    // Webcam-Bild hier verstecken um Platz zu schaffen
                    this.webcamContainer.Visibility = Visibility.Collapsed;
                }

                stopBarcodeRecognition();

                this.gridSearchingIndicator.Visibility = Visibility.Visible;
                this.labelSearchingIndicator.Text = "Suche...";
                this.SearchResultList.Visibility = Visibility.Hidden;

                searchProcess.CqlBuilder = new CQLBuilder();
                searchProcess.CqlBuilder.cqlTerms[configuration.SRUSearchAllTerm] = textBoxSearch.Text;
                searchProcess.StartSearch();
            }
        }


        public void searchProcess_ResultFound(object sender, Threads.SearchSRUProcessArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
            {
                stopBarcodeRecognition();

                Sources sources = e.Result;
                this.gridSearchingIndicator.Visibility = Visibility.Hidden;
                this.SearchResultList.Visibility = Visibility.Visible;
                int results = 0;

                if (sources != null && sources.Exception == null)
                {
                    if (sources != null && sources.Books != null)
                        results = sources.Books.Count;

                    this.labelSearchingIndicator.Text = "GEFUNDENE BÜCHER: " + results;

                    if (sources.Books != null)
                    {
                        setSearchResultsDataSource(sources);

                        if (sources.Books.Count > 0)
                        {
                            // Bücher mit leerer Ortsangabe herausfiltern
                            for (int i = 0; i < sources.Books.Count; i++)
                            {
                                if (!sources.Books[i].City.Contains("s.l."))
                                {
                                    editBook.setBookDataSource(sources.Books[i]);
                                    SearchResultList.SelectedIndex = i;
                                    break;
                                }
                            }                            
                        }
                    }
                }
                else if (sources != null)
                {
                    String message;
                    if (sources.Exception is SRU.Exceptions.SRUServiceException)
                    {
                        message = ((SRU.Exceptions.SRUServiceException)sources.Exception).Details;
                    }
                    else
                    {
                        message = "Es ist ein Fehler aufgetreten. \n" + sources.Exception.Message;
                    }
                    this.labelSearchingIndicator.Text = message;
                }
            }, null); 
        }

        private void stopBarcodeRecognition()
        {
            if (this.IsBarcodeRecognitionActive)
            {
                this.BarcodeScanHelper.Visibility = Visibility.Collapsed;
                webcam.Stop();
                barcodeProcess.Stop();
            }
        }

        private void ScanBarcode_Unloaded(object sender, RoutedEventArgs e)
        {
            stopBarcodeRecognition();
        }

        public void setSearchResultsDataSource(Sources books)
        {
            SearchResultList.ItemsSource = null;
            SearchResultList.ItemsSource = books.Books;
        }

        private void SearchResultList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            editBook.setBookDataSource((Book)SearchResultList.SelectedItem);
        }

        private void SearchResultList_MouseEnter(object sender, MouseEventArgs e)
        {
            ScrollViewer.SetVerticalScrollBarVisibility((DependencyObject) sender, ScrollBarVisibility.Auto);
        }

        private void SearchResultList_MouseLeave(object sender, MouseEventArgs e)
        {
            ScrollViewer.SetVerticalScrollBarVisibility((DependencyObject)sender, ScrollBarVisibility.Hidden);

        }

        private void textBoxSearch_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key != System.Windows.Input.Key.Enter) return;
            e.Handled = true; 
            startSearch();
        }

        private void shrinkWebcamImage()
        {
            this.BarcodeScanHelper.Visibility = Visibility.Collapsed;

            this.picturewebcam.Height = this.picturewebcam.Height * 0.75;
        }

        private void textBoxSearch_TextChanged(object sender, TextChangedEventArgs e)
        {

        }
    }
}
